#include <common.h>
#include <memory/paddr.h>


word_t vaddr_read(vaddr_t addr, int len, word_t pc) {
    return paddr_read(addr, 4, pc);
}

void vaddr_write(vaddr_t waddr, word_t wdata, char wmask, word_t pc) {
	if(wmask == 0x1) paddr_write(waddr,1,wdata, pc);//byte
	else if(wmask == 0x3) paddr_write(waddr,2,wdata, pc);//half-word
	else if(wmask == 0xF) paddr_write(waddr,4,wdata, pc);//word
    else paddr_write(waddr,0,wdata, pc);

}


uint32_t dummy[100] = {
	0x00000413,
	0x00009117,
	0xffc10113,
	0x00c000ef,
	0x00000513,
	0x00008067,
	0xff410113,
	0x00000517,
	0x01c50513,
	0x00112423,
	0xfe9ff0ef,
	0x00050513,
	0x00100073,
	0x0000006f
};

extern "C" int inst_read(svBit reset,int raddr,int pc){
    if(~reset){
        word_t data = paddr_read(raddr,4,pc);
        return data;
    } 
    else return 0;
}

// extern "C" void inst_write(svBit reset, int waddr, int wdata){
// 	paddr_write(waddr,4,wdata,0);
// }


// extern "C" int data_read(int raddr,int pc){
// 	//printf("DR:%#010x\n",raddr);
// 	return vaddr_read(raddr,4,pc);
// }

// extern "C" void data_write(int waddr, int wdata, char wmask,int pc){
// 	//printf("DW:%#010x,%#010x,%#010x\n",waddr,wdata,wmask);
// 	vaddr_write(waddr,wdata,wmask,pc);	
// }

extern "C" int data_read(svBit reset, int raddr,int pc){
    
	if(~reset) {
        int data = vaddr_read(raddr,4,pc);
        // printf("READ=%x,%x,%x\n",raddr,pc,data);
        return data;
    }
    else return 0;
    
}

extern "C" void data_write(svBit reset, int waddr, char wmask, int wdata,int pc){
	if(~reset) {
        // printf("WRITE=%x,%x,%x\n",pc,waddr,wdata);
        // if(pc==0) printf("READ");
        vaddr_write(waddr,wdata,wmask,pc);	
    }
}

uint32_t b2e_w(uint32_t value) { // 端序转换
    return ((value & 0x000000FF) << 24) |
           ((value & 0x0000FF00) << 8)  |
           ((value & 0x00FF0000) >> 8)  |
           ((value & 0xFF000000) >> 24);
}


extern "C" void flash_read(int32_t addr, int32_t *data) {
    uint32_t real_addr = addr + CONFIG_MBASE;
    uint32_t ret_data =  vaddr_read(real_addr,4,0);
    *data = b2e_w(ret_data);
}


extern "C" void mrom_read(int32_t addr, int32_t *data) { 
    printf("ERROR:No Permission To Read MROM In (%x)",addr);
    // *data = vaddr_read(addr,4,0);
}

extern "C" void psram_read(int32_t addr, int32_t *rdata) {
    printf("ERROR:No Permission To Read PSRAM In (%x)",addr);
    // uint32_t ret_data = vaddr_read(addr + CONFIG_DBASE_PSRAM,4,0);
    // // printf("[READ-START]raddr=%x,data=%x\n",addr + CONFIG_DBASE_PSRAM,ret_data);
    // *rdata = ret_data;
}

extern "C" void psram_write(int32_t addr, int32_t wdata, int32_t cnt) {
    printf("ERROR:No Permission To Write PSRAM In (%x)",addr);
    // printf("[WRITE-START]waddr=%x,wdata=%x,cnt=%x\n",addr + CONFIG_DBASE_PSRAM,wdata,cnt);
    // switch(cnt){
    //     case 2: vaddr_write(addr + CONFIG_DBASE_PSRAM,wdata,0x1,0);break;

    //     case 4: vaddr_write(addr + CONFIG_DBASE_PSRAM,wdata,0x3,0);break;

    //     case 8: vaddr_write(addr + CONFIG_DBASE_PSRAM,wdata,0xF,0);break;
        
    //     default: vaddr_write(addr + CONFIG_DBASE_PSRAM,wdata,0xF,0);break;
    // }
}


extern "C" void sdram_read(int row_addr, char bank_addr, const svOpenArrayHandle rdata){
	printf("READ=%x,%x\n",row_addr,bank_addr);
	uint16_t data_buf[512];
	memset(data_buf,0xF,sizeof(data_buf));

	int n_words = svSizeOfArray(rdata);
    uint16_t *cpp_ptr = (uint16_t*) svGetArrElemPtr(rdata, 0);
    for (int i = 0; i < n_words; ++i) {
        cpp_ptr[i] = data_buf[i];
    }
}


extern "C" void sdram_write(int addr, int wdata){
	printf("WRITE=%x,%x\n",addr,wdata);
}
